﻿using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace FreeDatabase
{
    class AudioDisc
    {
        public const int FramesPerSecond = 75;

        private List<Track> items;

        public AudioDisc(List<Track> items)
        {
            this.items = items;
        }

        public IList<Track> Tracks
        {
            get
            {
                return items.AsReadOnly();
            }
        }

        public static AudioDisc Read(string path)
        {
            var items = new SortedList<int, Track>();

            string[] paths = Directory.GetFiles(path, "*.cda");
            if (paths.Length > 0)
            {
                for (int i = 0; i < paths.Length; i++)
                {
                    byte[] buffer = File.ReadAllBytes(paths[i]);

                    // AAAABBBBCCCCDDDDEEEE ...

                    // A = "RIFF"
                    // B = 
                    // C = 
                    // D = 
                    // E = 

                    if (buffer[0] == 0x52 && buffer[1] == 0x49 &&
                        buffer[2] == 0x46 && buffer[3] == 0x46)
                    {
                        // ... AABBCCCCDDDDEEEEFFFFGGGG

                        // A = 
                        // B = 
                        // C = 
                        // D = 
                        // E = 
                        // F = Start
                        // G = Duration

                        var item = new Track(
                            new Timecode((int)buffer[38], (int)buffer[37], (int)buffer[36]),
                            new Timecode((int)buffer[42], (int)buffer[41], (int)buffer[40])
                        );

                        items.Add(item.Index, item);
                    }
                }
            }

            return new AudioDisc(items.Values.ToList());
        }
    }

    class Track
    {
        private Timecode start;
        private Timecode duration;

        public Track(Timecode start, Timecode duration)
        {
            this.start = start;
            this.duration = duration;
        }

        public Timecode Start
        {
            get
            {
                return start;
            }
        }

        public Timecode Duration
        {
            get
            {
                return duration;
            }
        }

        public int Index
        {
            get
            {
                return (start.Minutes * 60 + start.Seconds) * AudioDisc.FramesPerSecond 
                    + start.Frames;
            }
        }

        public int Length
        {
            get
            {
                return (duration.Minutes * 60 + duration.Seconds) * AudioDisc.FramesPerSecond 
                    + duration.Frames;
            }
        }
    }

    class Timecode
    {
        private int minutes;
        private int seconds;
        private int frames;

        public Timecode(int minutes, int seconds, int frames)
        {
            this.minutes = minutes;
            this.seconds = seconds;
            this.frames = frames;
        }

        public int Minutes
        {
            get
            {
                return minutes;
            }
        }

        public int Seconds
        {
            get
            {
                return seconds;
            }
        }

        public int Frames
        {
            get
            {
                return frames;
            }
        }
    }
}
